package com.dianping.cat.annotation;

import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


import java.lang.reflect.Method;

/**
 * 切点类
 * @author gj
 * @since 2015-03-14 Pm 10:35
 * @version 1.0
 */
@Aspect
@Component
public  class CatTransaction {

    //本地异常日志记录对象
    private  static  final Logger logger = LoggerFactory.getLogger(CatTransaction. class);
    //Service层切点
    @Pointcut("@annotation(com.dianping.cat.annotation.CatTransactionService)")
    public  void serviceAspect() {
    }
    //Controller层切点
    @Pointcut("@annotation(com.dianping.cat.annotation.CatTransactionController)")
    public  void controllerAspect() {
    }

//    private ThreadLocal threadlocal = new ThreadLocal();
    /**
     * 前置通知 用于拦截Controller层记录用户的操作
     *
     * @param joinPoint 切点
     */
    @Before("controllerAspect()")
    public  void doBefore(JoinPoint joinPoint) {

        try {
            //*========控制台输出=========*//
        }  catch (Exception e) {
            //记录本地异常日志
            logger.error("异常信息:{}", e.getMessage());
        }
    }

    //


    /**
     * 前置通知 配置环绕通知,使用在方法上注册的切入点
     */
    @Around("serviceAspect()")
    public  Object doServerAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        String desc = "";// 暂时不获取，考虑到性能 this.getServiceMthodDescription(joinPoint);
        Transaction t = Cat.getProducer().newTransaction("service:[" + targetName + "]", methodName + ":" + desc);
        logger.info("service:[" + targetName + "]", methodName + ":" + desc);
        try {
            Object obj = joinPoint.proceed();
            t.setStatus(Transaction.SUCCESS);
            return  obj;
        } catch (Throwable e) {
            Cat.logError("service:[" + targetName + "] methodName:[" + methodName + "]", e);
            t.setStatus(e);
            throw e;
        }finally {
            t.complete();
        }
    }

    /**
     * 前置通知 用于拦截Server层记录用户的操作
     */
//    @Before("serviceAspect()")
   /* public  void doServerBefore(JoinPoint joinPoint) {

        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            String desc = "";// 暂时不获取，考虑到性能 this.getServiceMthodDescription(joinPoint);
            Object[] arguments = joinPoint.getArgs();
//            for(int i = 0;i < arguments.length ; i++)
//                System.out.println("================"+arguments[i]);
            logger.info("====================="+targetName+"--"+methodName);
            Transaction t = Cat.getProducer().newTransaction("service:["+targetName+"]", methodName+":"+desc);
            threadlocal.set(t);
        }  catch (Exception ex) {
            //记录本地异常日志
            logger.error("异常信息:{}", ex.getMessage());
        }
    }*/

    /**
     * 前置通知 用于拦截Server层记录用户的操作
     */
//    @AfterReturning("serviceAspect()")
   /* public  void doServerAfterReturning(JoinPoint joinPoint) {
        try {
            Transaction t = (Transaction)threadlocal.get();
            t.setStatus(Transaction.SUCCESS);
        }  catch (Exception ex) {
            //记录本地异常日志
            logger.error("异常信息:{}", ex.getMessage());
        }
    }*/


    /**
     * 前置通知 用于拦截Server层记录用户的操作
     */
//    @After("serviceAspect()")
  /*  public  void doServerAfter(JoinPoint joinPoint) {
        try {
//            t.setStatus(Transaction.SUCCESS);
            Transaction t = (Transaction)threadlocal.get();
            t.complete();
        }  catch (Exception ex) {
            //记录本地异常日志
            logger.error("异常信息:{}", ex.getMessage());
        }
    }*/


    /**
     * 异常通知 用于拦截Server层记录用户的操作
     *
     * @param joinPoint
     * @param e
     */
//    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
   /* public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {

        try {
              *//*========控制台输出=========*//*
            Transaction t = (Transaction)threadlocal.get();

            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Cat.logError(targetName+":"+methodName,e);
            t.setStatus(e);
        }  catch (Exception ex) {
            //记录本地异常日志
            logger.error("异常信息:{}", ex.getMessage());

        }
    }*/
    /**
     * 获取注解中对方法的描述信息 用于service层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    public  static String getServiceMthodDescription(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(CatTransactionService.class).description();
                    break;
                }
            }
        }
        return description;
    }
    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(CatTransactionController.class).description();
                    break;
                }
            }
        }
        return description;
    }
}  
